% Devin Koepl

classdef BouncingBallClass < handle
  
  properties (Constant)
    A = [0, 1; 0, 0];
    N = [0; -9.81];
  end
  
  properties
    te;
    xe;
    ie;
    
    options;
    state_fun;
  end
  
  methods
      
    function obj = BouncingBallClass(x0)
        obj.te = 0;
        obj.xe = x0;
        obj.ie = 1;
        
        obj.options = {odeset('Events', @obj.flight_events, 'refine', 20)};
        obj.state_fun = {@obj.flight_state};
    end
      
    function [t, x] = run(obj)
        [t, x, obj.te, obj.xe, obj.ie] = ode45(obj.state_fun{obj.ie}, ...
            [obj.te, inf], obj.xe, obj.options{obj.ie});
        obj.xe(2) = -obj.xe(2);
    end
      
    function xdot = flight_state(obj, t, x)
        xdot = obj.A * x + obj.N;
    end

    function [value, isterminal, direction] = flight_events(obj, t, x)
        value = x(1);     % detect height = 0
        isterminal = 1;   % stop the integration
        direction = -1;   % negative direction
    end

  end
  
end